/**
 * 
 */
package com.google.code.netz.wfe;

import java.util.UUID;

import com.google.code.netz.wfe.api.ILifecycleHandler;
import com.google.code.netz.wfe.api.IWorkflowEngine;
import com.google.code.netz.wfe.api.WorkflowException;
import com.google.code.netz.wfe.events.CaseEvent;
import com.google.code.netz.wfe.events.EventManager;
import com.google.code.netz.wfe.events.CaseEvent.CaseEventType;
import com.google.code.netz.wfe.model.Activity;
import com.google.code.netz.wfe.model.ICase;
import com.google.code.netz.wfe.model.Resource;
import com.google.code.netz.wfe.model.State;
import com.google.code.netz.wfe.model.Transition;
import com.google.code.netz.wfe.model.WorkItem;

/**
 * @author <a href='mailto:rahul.thakur.xdev@gmail.com'>Rahul Thakur</a>
 * @since 1.0
 * @version $Id$
 */
public class DefaultWorkflowEngine implements IWorkflowEngine {

	private ILifecycleHandler<ICase<?>> caseLifecycleHandler = new CaseLifecycleHandler();

	private ILifecycleHandler<Transition<?>> transitionLifecycleHandler = new TransitionLifecycleHandler();

	private ILifecycleHandler<WorkItem<?>> workItemLifecycleHandler = new WorkItemLifecycleHandler();

	private ILifecycleHandler<Activity> activityLifecycleHandler = new ActivityLifecycleHandler();

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.IWorkflowEngine#query(java.util.UUID,
	 *      com.google.code.netz.wfe.model.Resource)
	 */
	@Override
	public State query(UUID kaseId, Resource resource) throws WorkflowException {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.IWorkflowEngine#submit(com.google.code.netz.wfe.model.ICase,
	 *      com.google.code.netz.wfe.model.Resource)
	 */
	@Override
	public <D> WorkItem<D> submit(ICase<D> kase, Resource resource) throws WorkflowException {
		// EventManager.getInstance().dispatchEvent(
		// new CaseEvent(kase, CaseEventType.CASE_SUBMITTED));
		// TODO : Check if the specified resource is allowed to submit this
		// ICase instance.
		// if NOT, then throw a Workflow Exception.
		if (true) {
			synchronized (this) {
				// TODO: Case status should be updated in a synchronized block
				if (kase.getCurrentState() == State.STATE_DEFAULT) {
					kase.setCurrentState(State.STATE_ENABLED);
					EventManager.getInstance().dispatchEvent(new CaseEvent<ICase>(kase, CaseEventType.CASE_SUBMITTED));
				} else
					throw new WorkflowException(String.format(
							"Case %s could not be started, it is not in a default state.", kase.getLabel()));
			}
			return accept(kase, resource);
		}
		return null;
	}

	/**
	 * 
	 * @param <D>
	 * @param kase
	 * @param resource
	 * @return
	 * @throws WorkflowException
	 */
	private <D> WorkItem accept(ICase<D> kase, Resource resource) throws WorkflowException {
		// TODO : Check if the specified resource is allowed to submit this
		// ICase instance.
		// if NOT, then throw a Workflow Exception.
		if (true) {
			// Replace with context
			caseLifecycleHandler.start(kase, new Object() /* TODO: Replace! */);
			return new WorkItem<D>(kase, kase.getInitialTransition());
		}
		return null;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.IWorkflowEngine#close(com.google.code.netz.wfe.model.ICase,
	 *      com.google.code.netz.wfe.model.Resource)
	 */
	@Override
	public <D> void close(ICase<D> kase, Resource resource) throws WorkflowException {
		// TODO : Check if the specified resource is allowed to submit this
		// ICase instance.
		// if NOT, then throw a Workflow Exception.
		if (true) {
			// Replace with context
			caseLifecycleHandler.stop(kase, new Object() /* TODO: Replace! */);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.IWorkflowEngine#open(com.google.code.netz.wfe.model.WorkItem,
	 *      com.google.code.netz.wfe.model.Resource)
	 */
	@Override
	public Activity open(WorkItem wi, Resource resource) throws WorkflowException {
		// TODO : Check if the specified resource is allowed to submit this
		// ICase instance.
		// if NOT, then throw a Workflow Exception.
		if (true) {
			// Replace with context
			workItemLifecycleHandler.start(wi, new Object());
			Activity activity = new Activity(wi, resource);
			activity.setActive(true);
			return activity;
		}
		return null;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.IWorkflowEngine#resume(com.google.code.netz.wfe.model.ICase,
	 *      com.google.code.netz.wfe.model.Resource)
	 */
	@Override
	public <D> void resume(ICase<D> kase, Resource resource) throws WorkflowException {
		// TODO : Check if the specified resource is allowed to submit this
		// ICase instance.
		// if NOT, then throw a Workflow Exception.
		if (true) {
			// Replace with context
			caseLifecycleHandler.resume(kase, new Object() /* TODO: Replace! */);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.IWorkflowEngine#suspend(com.google.code.netz.wfe.model.ICase,
	 *      com.google.code.netz.wfe.model.Resource)
	 */
	@Override
	public <D> void suspend(ICase<D> kase, Resource resource) throws WorkflowException {
		// TODO : Check if the specified resource is allowed to submit this
		// ICase instance.
		// if NOT, then throw a Workflow Exception.
		if (true) {
			// Replace with context
			caseLifecycleHandler.suspend(kase, new Object() /* TODO: Replace! */);
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.IWorkflowEngine#close(com.google.code.netz.wfe.model.Activity,
	 *      com.google.code.netz.wfe.model.Resource)
	 */
	@Override
	public void close(Activity activity, Resource resource) throws WorkflowException {
		// TODO : Check if the specified resource is allowed to submit this
		// ICase instance.
		// if NOT, then throw a Workflow Exception.
		if (true) {
			// Replace with context
			activityLifecycleHandler.stop(activity, new Object());
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see com.google.code.netz.wfe.api.IWorkflowEngine#fire(com.google.code.netz.wfe.model.Transition,
	 *      com.google.code.netz.wfe.model.Resource)
	 */
	@Override
	public void fire(Transition transition, Resource resource) throws WorkflowException {
		// TODO : Check if the specified resource is allowed to submit this
		// ICase instance.
		// if NOT, then throw a Workflow Exception.
		if (true) {
			// Replace with context
			transitionLifecycleHandler.start(transition, new Object());
		}
	}

}
